package com.xy.biz.xd.service.impl;


import com.xy.biz.fd.client.DocumentClient;
import com.xy.biz.fd.client.RepositoryEventBusClient;
import com.xy.biz.fd.domain.DocumentPermissions;
import com.xy.biz.xd.domain.enums.DocumentReleaseStatusEnum;
import com.xy.biz.xd.domain.query.DocumentReleaseQuery;
import com.xy.tool.constant.DocumentExtension;
import com.xy.biz.fd.domain.req.document.SaveDocumentRequest;
import com.xy.biz.fd.domain.resp.GetDocumentResponse;
import com.xy.biz.uc.client.UserClient;
import com.xy.biz.uc.domain.dto.UserDTO;
import com.xy.biz.xd.domain.bo.DocumentReleaseBO;
import com.xy.biz.xd.domain.converter.DocumentReleaseConverter;
import com.xy.biz.xd.domain.req.GenerateDocumentRequest;
import com.xy.biz.xd.domain.req.ListLedgerDataRequest;
import com.xy.biz.xd.domain.resp.GetDocumentReleaseResponse;
import com.xy.biz.xd.domain.strategy.ExcelModelStrategy;
import com.xy.biz.xd.manager.DocumentReleaseCheckManager;
import com.xy.biz.xd.service.DocumentReleaseService;
import com.xy.biz.xd.service.LedgerService;
import com.xy.lang.domain.Page;
import com.xy.lang.domain.Result;

import com.xy.lang.util.ResultUtils;
import com.xy.tool.context.UserContextHolder;
import com.xy.tool.gid.service.GidService;
import com.xy.tool.minio.util.MinioUtil;
import com.xy.tool.util.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Greekn Zhang
 * @date 2021/7/1 13:44
 * @description
 */
@Slf4j
@Service
public class LedgerServiceImpl implements LedgerService {

    @Autowired
    private Map<String, ExcelModelStrategy> generatorMap;
    @Autowired
    private MinioUtil minioUtil;
    @Autowired
    private GidService gidService;
    @Autowired
    private UserClient userClient;
    @Autowired
    private DocumentClient documentClient;
    @Autowired
    private RepositoryEventBusClient repositoryEventBusClient;
    @Autowired
    private DocumentReleaseService documentReleaseService;
    @Autowired
    private DocumentReleaseCheckManager documentReleaseCheckManager;

    /**
     * 生成表格
     */
    @Override
    public Result<?> generate(GenerateDocumentRequest request) {
        //生成Excel
        FileInputStream inputStream = null;
        long mpath = gidService.generate();
        String serverFolder = FileUtils.getPath();
        String path = null;
        if (request.getType() == 0) {
            Integer gen = request.getGenerateType();
            OutputStream out = null;
            SXSSFWorkbook workbook = null;
            try {
                path = mpath + DocumentExtension.EXCELX;
                out = new FileOutputStream(serverFolder + path);
                workbook = generatorMap.get(ExcelModelStrategy.EXCEL_MOD + gen).generate(request);
                workbook.write(out);
                inputStream = new FileInputStream(serverFolder + path);
                //删除原临时文件
                FileUtils.delPath(serverFolder + path);
            } catch (Exception e) {
                log.error(e.getMessage());
            } finally {
                try {
                    workbook.close();
                    out.close();
                } catch (Exception e) {
                    log.error("At IO close：" + e.getMessage());
                }
            }
        }
        Long size = null;
        try {
            size = minioUtil.uploadFile(inputStream, path, MinioUtil.storageBucket);
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            if (size == null) {
                return Result.fail();
            }
        }
        LocalDateTime now = LocalDateTime.now();
        SaveDocumentRequest build = SaveDocumentRequest.builder()
                .documentName(request.getDocumentName())
                .documentType(2)
                .folderId(0L)
                .repositoryId(0L)
                .status(0)
                .fileExtension(DocumentExtension.EXCELX)
                .fileSize(size)
                .path(path)
                .location("")
                .level(0)
                .version("A0")
                .threadId(0L)
                .tenantId(0L)
                .permission(DocumentPermissions.getAllPermissions())
                .accessTime(now)
                .createUserId(UserContextHolder.getUserId())
                .createTime(now)
                .updateTime(now)
                .documentFlowLock(false)
                .deleteFlag(false)
                .build();
        GetDocumentResponse getDocumentResponse = ResultUtils.get(documentClient.saveDocument(build));
        //将文件移到固定文件夹下
        repositoryEventBusClient.firerRepositoryHandler(getDocumentResponse.getDocumentId());
        return Result.success(getDocumentResponse.getDocumentId());
    }

    /**
     * 查找生效文件
     * @param request
     */
    @Override
    public Page<GetDocumentReleaseResponse> listEffect(ListLedgerDataRequest request) {
        //获取所有现行的文件
        Integer startIndex = request.getPageIndex() * request.getPageSize();
        Integer endIndex = startIndex + request.getPageSize();
        //获取所有发行生效的流程
        List<DocumentReleaseBO> documentReleaseBOS = documentReleaseService.listDocumentRelease(DocumentReleaseQuery.max().documentCode(request.getDocumentCode()).effectFlag(true).status(DocumentReleaseStatusEnum.RELEASE.getCode()).build());
        Map<String, DocumentReleaseBO> filteredDocumentReleaseBOS = documentReleaseBOS.stream().collect(Collectors.toMap(DocumentReleaseBO::getDocumentCode, e -> e, (e1, e2) -> e1));
        documentReleaseBOS = new ArrayList<>(filteredDocumentReleaseBOS.values());
        List<GetDocumentReleaseResponse> getDocumentReleaseResponses = DocumentReleaseConverter.toResponse(documentReleaseBOS);
        endIndex = getDocumentReleaseResponses.size() < endIndex ? getDocumentReleaseResponses.size() : endIndex;
        getDocumentReleaseResponses = getDocumentReleaseResponses.subList(startIndex, endIndex);
        Set<Long> userIds = getDocumentReleaseResponses.stream().map(GetDocumentReleaseResponse::getCreateUserId).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(userIds)) {
            Map<Long, String> map = ResultUtils.get(userClient.listUserById(userIds)).stream().collect(Collectors.toMap(UserDTO::getUserId, UserDTO::getUserName));
            getDocumentReleaseResponses.forEach(d -> {
                d.setCreateUserGroupName(map.get(d.getCreateUserId()));
            });
        }
        return new Page<>(getDocumentReleaseResponses, CollectionUtils.isEmpty(documentReleaseBOS) ? 0 : documentReleaseBOS.size());
    }
}
